package com.cnswhy.cloud.common.core.utils;

import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;


/**
 * @Description:    高并发场景下System.currentTimeMillis()的性能问题的优化
 * @UpdateUser:     chuck
 * @UpdateDate:     2018/11/30 22:23
 * @Version:        1.0
 * @UpdateRemark:
 */
public class SystemClockUtil {
    private static final String THREAD_NAME = "system.clock";
    private static final SystemClockUtil MILLIS_CLOCK = new SystemClockUtil(1);
    private final long precision;
    private final AtomicLong now;
    private SystemClockUtil(long precision) {
        this.precision = precision;
        now = new AtomicLong(System.currentTimeMillis());
        scheduleClockUpdating();
    }
    public static SystemClockUtil millisClock(){
        return MILLIS_CLOCK;
    }
    private void scheduleClockUpdating(){
        ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(runnable -> {
            Thread thread = new Thread(runnable, THREAD_NAME);
            thread.setDaemon(true);
            return thread;
            });
        scheduler.scheduleAtFixedRate(() ->
                now.set(System.currentTimeMillis()), precision, precision, TimeUnit.MILLISECONDS);
    }

    public long now() {
        return now.get();
    }
    public static long currentTimeMillis() {
        return SystemClockUtil.millisClock().now.get();
    }
    public static Date getDate() {
        return new Date(SystemClockUtil.millisClock().now());
    }
    public static LocalDateTime getLocalDateTime(){
        return LocalDateTime.ofEpochSecond(SystemClockUtil.millisClock().now() /1000,0, ZoneOffset.ofHours(8));
    }
    public static String getSettDateyyyyMMdd(){
        return new SimpleDateFormat("yyyyMMdd").format(new java.util.Date(SystemClockUtil.millisClock().now()));
    }

    public static void main(String[] args) {
        System.out.println(SystemClockUtil.getLocalDateTime());
    }
}
